package com.puzzlebazar.client.puzzle.model;

import java.io.Serializable;

import com.google.gwt.user.client.ui.HasText;
import com.puzzlebazar.client.puzzleinfo.NewPuzzleInfo;
import com.puzzlebazar.client.puzzleinfo.PuzzleInfo;
import com.puzzlebazar.client.squaregrid.view.ComponentHighlighter;
import com.puzzlebazar.client.util.ConnectionLock;
import com.puzzlebazar.client.util.Observable;
import com.puzzlebazar.client.util.Vec2i;

public interface PuzzleModel extends Observable, Serializable {

	/**
	 * @return The key of the puzzle info structure associated with this object
	 */
	public String getPuzzleInfoKey();

	/**
	 * @return The number of columns / rows
	 */
	public Vec2i getSize();

	/**
	 * Clear the entire content of the model. The model must assume
	 * that the grid size can have changed and should check it.
	 * The user should call notifyObserver( moveList ) after this.
	 * Derived children should call clear() on their superclass.
     *
     * @param time The time at which the clear move is executed
	 * @return A clear puzzle move
	 */
	public Move clear( long time );
	
	/**
	 * Get a move list to recreate the entire model. The moves must be
	 * returned in a legal order, but not necessarily in the order in 
	 * which they were created.
	 * 
	 * @return A move list that recreates the current state of the model
	 */
	public MoveList getMoveList();
		
	
	/**
	 * Creates the puzzle model on the server, together with its PuzzleInfo
	 * 
	 * @param newPuzzleInfo The information required to create this model on the server
	 */
	public void create( NewPuzzleInfo newPuzzleInfo );

	/**
	 * Attaches this puzzle model with the specified puzzle info. The information
	 * will be saved the next time savePuzzle is called
	 * 
	 * @param puzzleInfo The puzzle information to attach this model to
	 */
	void attach(PuzzleInfo puzzleInfo);

	/**
	 * Save the current puzzle
	 * The user should call notifyObserver( move ) after this.
	 * 
	 * @param lock The lock to use when connecting to the server
	 * @return A save puzzle move
	 */
	public Move savePuzzle( ConnectionLock lock );

	/**
	 * Checks that the current model logically match with its
	 * internal solution. Will return false if the puzzle doesn't
	 * have an internal solution.
	 * 
	 * @return True if the puzzle matches its solution, false otherwise
	 */
	public boolean checkSolution();
	
	/**
	 * Sets the current puzzle state as its internal solution and clears
	 * the current puzzle state. This method is usually used after the puzzle
	 * has been loaded, in order to clear it and let the user solve it.
	 * The caller should make sure to call
	 * notifyObservers() on the model after this.
	 * 
	 * @return A move list indicating the operations to perform to set 
	 *         the current state as solution
	 */
	public Move setCurrentStateAsSolution();
	
	/**
	 * @return True if the model, in its current form, has been saved. False otherwise.
	 */
	public boolean isSaved();

	/**
	 * @return The factory associated with the current model
	 */
	public PuzzleFactory getFactory();


	/**
	 * Checks that the current solution of the model is valid
	 *
	 * @param highlighter Object that can be used to highlight the faulty elements (can be null for no highlighting)
	 * @param textArea An object into which error messages should be printed out (can be null for no messages)
	 * @return True if the solution is valid, false otherwise
	 */
	public boolean isSolutionValid( ComponentHighlighter highlighter, HasText textArea );

	/**
	 * Sets the current message associated with the puzzle model
	 * 
	 * @param message The message to set
	 * @param time the time at which to set the message
	 * @return The move corresponding to the message that was added
	 */
	public MoveMessage setMessage(String message, long time);

	/**
	 * Access the message currently associated with the puzzle model
	 * 
	 * @return The message
	 */
	public String getMessage();

	
}
